package de.jmda.mview.fx.node.typeshape.relation;

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.geometry.Point2D;
import javafx.scene.input.MouseEvent;
import de.jmda.fx.node.Line;
import de.jmda.fx.node.behaviour.BehaviourMouseDraggingStop;
import de.jmda.fx.node.behaviour.DraggingData;

/**
 * Simple relation segment that connects {@link Line#startPointProperty()} and
 * {@link Line#endPointProperty()} with a vertical line.
 *
 * @author roger.jmda@gmail.com
 */
public class RelationSegmentVertical extends RelationSegmentOrthogonal
{
	/**
	 * @param start observable starting point for relation segment
	 * @param yEndProvider observable point providing y coordinate of end point
	 *                     for relation segment
	 */
	public RelationSegmentVertical(
			ObjectProperty<Point2D> start, ObjectProperty<Point2D> yEndProvider)
	{
		super(
				start,
				new SimpleObjectProperty<Point2D>(
						new Point2D(start.get().getX(), yEndProvider.get().getY())));
		
		start.addListener(new StartPointUpdater<Point2D>());
		yEndProvider.addListener(new EndPointUpdater<Point2D>());
	}

	@Override
	public void activateDragging()
	{
		BehaviourMouseDraggingData behaviourMouseDraggingData =
				new BehaviourMouseDraggingData();
		new BehaviourMouseDraggingStartLine(   this, behaviourMouseDraggingData);
		new BehaviourMouseDraggingStop(        this, behaviourMouseDraggingData);
		new BehaviourMouseDraggingLineVertical(this, behaviourMouseDraggingData);
	}

	private class StartPointUpdater<T extends Point2D>
			implements ChangeListener<Point2D>
	{
		@Override
    public void changed(ObservableValue<? extends Point2D> observable,
        Point2D oldValue, Point2D newValue)
    {
			setStartX(newValue.getX());
			setStartY(newValue.getY());

			setEndX(getStartX());
    }
	}
	
	private class EndPointUpdater<T extends Point2D>
			implements ChangeListener<Point2D>
	{
		@Override
    public void changed(ObservableValue<? extends Point2D> observable,
        Point2D oldValue, Point2D newValue)
    {
			setEndY(newValue.getY());
    }
	}

	public class BehaviourMouseDraggingLineVertical
			extends BehaviourMouseDraggingLine
	{
		public BehaviourMouseDraggingLineVertical(
				Line line, BehaviourMouseDraggingData behaviourMouseDraggingData)
    {
	    super(line, behaviourMouseDraggingData);
    }

		/**
		 * Sets new x coordinates to line, allows horizontal movement, prohibits
		 * vertical movement. 
		 *
		 * @see de.jmda.fx.node.Line.BehaviourMouseDraggingLine#showBehaviour(javafx.scene.input.MouseEvent)
		 */
		@Override
	  public void showBehaviour(MouseEvent mouseEventCurrent)
	  {
			DraggingData lineDraggingData =
					getLineDraggingData(
							mouseEventCurrent, line, behaviourMouseDraggingData);

			double startPointX = line.getStartPoint().getX() + lineDraggingData.getDragX();
			double endPointX   = line.getEndPoint().getX()   + lineDraggingData.getDragX();

			// set line start and end x coordinates to new values
			line.setStartX(startPointX);
			line.setEndX(    endPointX);
			
			behaviourMouseDraggingData.setMouseDragging(mouseEventCurrent);
	  }
	}
}